/**
 * eCommerce Application Sample for J2EE Training
 * @author Fabienne Boyer - july 2000
 * @author Didier Donsez - november 2002
 */
package shell;

import ecom.cart.CartLocal;
import ecom.session.EcomAdminRemote;
import ecom.session.EcomCustomerRemote;
import java.io.*;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Iterator;
import java.io.PrintStream;

public /*abstract*/ class Shell implements Runnable, ShellConstantes {

    private TreeMap _commandNameMap = new TreeMap();
    private ShellContext _context = new ShellContextImpl(_commandNameMap);
    private boolean stop = false;
    protected InputStream in;
    protected PrintStream out;
    protected PrintStream err;

    public Shell(String args[], EcomCustomerRemote customerBean, EcomAdminRemote adminBean, Boolean admin, CartLocal cartLocal) {

        out = System.out;
        err = System.err;

        if (!parseArgs(args)) {
            stop();
        }

        ShellContext context = getContext();
        // Add "context" command.
        addCommand(new VarCommandImpl(context));

        // Add "echo" command.
        addCommand(new EchoCommandImpl(context));

        // Add "help" command.
        addCommand(new HelpCommandImpl(context));

        addCommand(new AccountCommandImpl(context));

        addCommand(new CustomerCommandImpl(context));

        addCommand(new BatchCommandImpl(context));
        
        addCommand(new ProductCommandImpl(context));
        
        addCommand(new CategoryCommandImpl(context));

        addCommand(new StoreCommandImpl(context));

        addCommand(new CartCommandImpl(context));



        // Add "prompt" command.
//		addCommand(new PromptCommandImpl(context));

        // Add "quit" command.
        addCommand(new shell.SimpleQuitCommandImpl(context));

        // put the EBs' homes in the context
        context.setVar(PROMPT, "->");
        context.setVar(BANNER, getBanner());
        context.setVar("customerBean", customerBean);
        context.setVar("adminBean", adminBean);
        context.setVar("admin",admin);
        context.setVar("shellMaster", this);
        context.setVar("cartLocal", cartLocal);
        
    }

    protected boolean parseArgs(String args[]) {
        if (args.length < 1) {
            in = System.in;
            return true;
        } else {
            try {
                in = new FileInputStream(args[0]);
                return true;
            } catch (java.io.FileNotFoundException f) {
                err.println("File \"" + args[0] + "\"not found");
                return false;
            }

        }
    }

    protected final ShellContext getContext() {
        return _context;
    }

    protected final void stop() {
        stop = true;
    }

    public final void run() {
        String banner;
        String line;
        BufferedReader br = null;
        if (!stop) {
            banner = (String) _context.getVar(BANNER);
            if (banner != null) {
                out.println(banner);
            }
            line = null;

            br = new BufferedReader(new InputStreamReader(in));

        }

        while (!stop) {
            String prompt;
            prompt = (String) _context.getVar(PROMPT);
            if (prompt == null) {
                prompt = ">";
            }
            out.print(prompt);

            try {
                line = br.readLine();
            } catch (IOException ex) {
                err.println("Could not read input, please try again.");
                continue;
            }


            line = line.trim();

            if (line.length() == 0) {
                continue;
            }

            try {
                executeCommand(line, out, err);
            } catch (Exception ex) {
                err.println("Shell: " + ex);
            }
        }
    }

    private String getBanner() {
        StringBuffer sb = new StringBuffer();
        sb.append("\n-------------------------------------------------");
        sb.append("\n|                 WINERY                        |");
        sb.append("\n|                                               |");
        sb.append("\n-------------------------------------------------");
        return sb.toString();
    }

    protected final synchronized void removeCommand(String name) {
        out.println("Removing command  : " + name);
        _commandNameMap.remove(name);
    }

    protected final synchronized void executeCommand(
            String commandLine, PrintStream out, PrintStream err) throws Exception {
        commandLine = commandLine.trim();
        String commandName = (commandLine.indexOf(' ') >= 0)
                ? commandLine.substring(0, commandLine.indexOf(' ')) : commandLine;
        ShellCommand command = getCommand(commandName);
        if (command != null) {
            command.execute(commandLine, out, err);
        } else {
            err.println("Command not found.");
        }
    }

    protected final synchronized ShellCommand getCommand(String name) {
        ShellCommand sc = (ShellCommand) _commandNameMap.get(name);
        return sc;
    }

    protected final synchronized void addCommand(ShellCommand sc) {
        _commandNameMap.put(sc.getName(), sc);
    }

    protected final synchronized void clearCommands() {
        _commandNameMap.clear();
    }
}
